package com.lanyou.cook.web;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Tuple;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.lanyou.cook.common.Constants;
import com.lanyou.cook.datadictionary.InterfaceOperation;
import com.lanyou.cook.datadictionary.UserLogOpt;
import com.lanyou.cook.entity.domain.Field;
import com.lanyou.cook.entity.domain.FieldSystem;
import com.lanyou.cook.entity.domain.SystemInterface;
import com.lanyou.cook.entity.domain.userManagement.User;
import com.lanyou.cook.repository.FieldSystemRepository;
import com.lanyou.cook.repository.SystemInterfaceRepository;
import com.lanyou.cook.service.InterfaceVersionHistoryService;
import com.lanyou.cook.service.UserLogService;
import com.lanyou.cook.service.security.UserSessionService;
import com.lanyou.cook.util.DateUtil;
import com.lanyou.cook.web.param.SystemInterfaceParam;
import com.lanyou.cook.web.vo.FieldSystemInterfaceCount;
import com.lanyou.esb.datadictionary.ForwardStatus;
import com.lanyou.esb.entity.Http;
import com.lanyou.esb.entity.StoreForward;
/**
 * 
 * @author 曾族根
 *
 */
@RestController
@RequestMapping(Constants.BASE_URL_API + "/systemInterfaces")
public class SystemInterfaceController {
	@Autowired
	UserSessionService userSessionService;
	@PersistenceContext
	private EntityManager entityManager;
	@Autowired
	private SystemInterfaceRepository systemInterfaceRepository;
	
	@Autowired
	private FieldSystemRepository fieldSystemRepository;
	@Autowired
	private InterfaceVersionHistoryService interfaceVersionHistoryService;
	@Autowired
	private UserLogService userLogService;
	
	/**
	 * 查询系统接口
	 * @param param 类型:SystemInterfaceParam
	 * @param pageable 类型:Pageable 
	 * @return 参数条件下的系统接口
	 */
	@RequestMapping("/search/findByExample")
	@RequiresPermissions(value={"fieldInterfaceBasicInfoQuery:view"})
	public Page<SystemInterface> findByExample(SystemInterfaceParam param,Pageable pageable){
		
		Specification<SystemInterface> spec = new Specification<SystemInterface>() {
			@Override
			public Predicate toPredicate(Root<SystemInterface> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicatesList = new ArrayList<>();
				
				if(StringUtils.isNotBlank(param.getFieldId())){
					predicatesList.add(cb.equal(root.get("ownerFieldSystem").get("field").get("id"), param.getFieldId()));
				}
				Path<String> pathOwnerFieldSystemId = root.get("ownerFieldSystem").get("id");
				if(StringUtils.isNoneBlank(param.getFieldSystemId())){
					predicatesList.add(cb.equal(pathOwnerFieldSystemId,param.getFieldSystemId()));
				}else{
					// 默认查当前登录用户所管理的领域系统
					Collection<String> fieldSystemIds = userSessionService.findFieldSystemIdsOfCurrentAuthenticatedUserCanManage();
					if(!CollectionUtils.isEmpty(fieldSystemIds)){
						predicatesList.add(pathOwnerFieldSystemId.in(fieldSystemIds));
					}else {
						predicatesList.add(cb.notEqual(cb.literal(1), 1));
					}
					
				}
				if(StringUtils.isNotBlank(param.getJobName())){
					predicatesList.add(cb.like(root.get("jobName"), '%' + param.getJobName() + '%'));
				}
				if(StringUtils.isNotBlank(param.getInterfaceScene())){
					predicatesList.add(cb.equal(root.get("interfaceScene"), param.getInterfaceScene()));
				}
				if(StringUtils.isNotBlank(param.getReceiverDBType())){
					predicatesList.add(cb.equal(root.get("receiverDBType"), param.getReceiverDBType()));
				}
				if(StringUtils.isNotBlank(param.getSenderDBType())){
					predicatesList.add(cb.equal(root.get("senderDBType"), param.getSenderDBType()));
				}
				if(StringUtils.isNotBlank(param.getTecStandard())){
					predicatesList.add(cb.equal(root.get("tecStandard"), param.getTecStandard()));
				}
				if(StringUtils.isNotBlank(param.getReceiverFieldSystem())){
					predicatesList.add(cb.equal(root.get("receiverFieldSystem").get("id"), param.getReceiverFieldSystem()));
				}
				if(StringUtils.isNotBlank(param.getSenderFieldSystem())){
					predicatesList.add(cb.equal(root.get("senderFieldSystem").get("id"), param.getSenderFieldSystem()));
				}
				//时间
				DynaBean fixedDates = DateUtil.fixBeginTimeAndEndTime(param.getBeginOfCreateTime(), param.getEndOfCreateTime());
				Date fixedBeginTime = (Date)fixedDates.get("begin");
				Date fixedEndTime = (Date)fixedDates.get("end");
				
				Path<Date> pathDate = root.get("createTime");	
				predicatesList.add(cb.or(cb.isNull(pathDate), cb.between(pathDate, fixedBeginTime, fixedEndTime)));
				
				query.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
				return null;
			}
		};
		return systemInterfaceRepository.findAll(spec, pageable);
	}
	
	
	private static GsonBuilder gsonBuilder1 = new GsonBuilder()
			.addSerializationExclusionStrategy(new ExclusionStrategy() {
				@Override
				public boolean shouldSkipField(FieldAttributes f) {
					if (SystemInterface.class == f.getDeclaringClass()) {
						if (Arrays.asList("id", "jobName").contains(f.getName()))
							return false;
					}
					return true;
				}

				@Override
				public boolean shouldSkipClass(Class<?> clazz) {
					return false;
				}
			});
	/**
	 * 领域系统combobox关联
	 * @param fieldSystemId
	 * @return
	 */
	@RequestMapping(value="/search/findByOwnerFieldSystem_Id", produces="application/json")
	public String findByOwnerFieldSystem_Id(String fieldSystemId) {
		String Interfaces = "";
		Gson gson = new Gson();
		List<SystemInterface> systemInterfaces = systemInterfaceRepository.findByOwnerFieldSystem_Id(fieldSystemId);
		if(!systemInterfaces.isEmpty()){
			Interfaces = gsonBuilder1.create().toJson(systemInterfaces, new TypeToken<List<SystemInterface>>() {}.getType());
		}else{
			SystemInterface systemInterface = new SystemInterface();
			systemInterface.setId("");
			systemInterface.setJobName("请选择");
			systemInterfaces.add(systemInterface);
			Interfaces = gson.toJson(systemInterfaces);
			
		}
		return Interfaces;
	}
	
	/**
	 * 统计接口数
	 * @param fieldId 类型:String
	 * @param fieldSystemId 类型:String
	 * @return  领域，系统，接口数
	 */
	//统计查询功能
	@RequiresPermissions(value={"fieldSystemInterfaceStatistics:view"})
	@RequestMapping(value = "/statistics/byFieldAndFieldSystem", produces = "application/json")
	public Page<FieldSystemInterfaceCount> countByFieldAndFieldSystem(String fieldId, String fieldSystemId, Pageable pageable,String ifnull,String interfaceType) {
			String nothing="";	
			if(fieldId==null){
				fieldId ="";
			};
			if(fieldSystemId==null){
				fieldSystemId ="";
			};
			if(ifnull==null){
				ifnull ="";
			};
			if(interfaceType==null){
				interfaceType ="";
			};
			if(StringUtils.equals(ifnull, "无"))
			{
				ifnull ="";
				nothing = "0";
			};
			if(StringUtils.equals(interfaceType, "全部"))
			{
				interfaceType="";
			};
			int page1, page2;
			page1 = pageable.getPageNumber()*pageable.getPageSize();
			page2 = pageable.getPageSize();
			User user = userSessionService.getCurrentAuthenticatedUser();
			String userId = user.getId();
			
			List<Object[]> countInterfaceBySystem = systemInterfaceRepository.countInterfaceBySystem(userId, fieldId, fieldSystemId, ifnull, nothing, interfaceType, page1, page2);
			List<Object[]> countInterfaceBySystemForPage = systemInterfaceRepository.countInterfaceBySystemForPage(userId, fieldId, fieldSystemId, nothing, interfaceType, ifnull);
			List<FieldSystemInterfaceCount> result = new ArrayList<FieldSystemInterfaceCount>(countInterfaceBySystemForPage.size());
			int total = countInterfaceBySystemForPage.size();
			
			for (Object[] interfaces : countInterfaceBySystem) {
				FieldSystemInterfaceCount fieldSystemInterfaceCount = new FieldSystemInterfaceCount();
				fieldSystemInterfaceCount.setFieldName(interfaces[1] != null ? (String) interfaces[1]: "");
				fieldSystemInterfaceCount.setSystemName(interfaces[3] != null ? (String) interfaces[3] : "");
				String num6 = interfaces[5].toString();
				long num=Integer.parseInt(num6);
				fieldSystemInterfaceCount.setInterfaceAmount(interfaces[5] != null ? num : 0);
				fieldSystemInterfaceCount.setInterfaceType(interfaces[4] != null ? (String) interfaces[4]: "");
				result.add(fieldSystemInterfaceCount);
			}
			Page<FieldSystemInterfaceCount> page3 = new PageImpl<FieldSystemInterfaceCount>(result, pageable, total);
			return page3;
			
	}
		/**
		 * 统计系统数
		 * @param field 类型:String
		 * @param fieldSystem 类型:String 
		 * @param systemInterface 类型:String
		 * @return 统计的系统数
		 */
		//系统数统计
		private List<Tuple> systemStatistics(String field,String fieldSystem,String systemInterface) {
			CriteriaBuilder cb = entityManager.getCriteriaBuilder();
			CriteriaQuery<Tuple> cq = cb.createTupleQuery();

			// 构建FROM
			Root<Field> rootField = cq.from(Field.class);
			Join<Field, FieldSystem> rootSystem = rootField.join("fieldSystems", JoinType.LEFT);
			
			// 构建WHERE部分
			List<Predicate> predicatesList = new ArrayList<>();
			Collection<String> fieldSystemIds = userSessionService.findFieldSystemIdsOfCurrentAuthenticatedUserCanManage();
			predicatesList.add(rootSystem.get("id").in(fieldSystemIds));
			cq.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
			
			// 构建GROUP BY部分
			cq.groupBy(rootField.get("name"));

			// 构建SELECT部分
			cq.multiselect(rootField.get("name").alias("name"),rootField.get("id").alias("id"),
					cb.count(rootSystem).alias("systemAmount"));
			// 执行查询
			TypedQuery<Tuple> q = entityManager.createQuery(cq);
			List<Tuple> queryResult = q.getResultList();
			return queryResult;
		}
		/**
		 * 统计作业数
		 * @param field 类型:String
		 * @param fieldSystem 类型:String
		 * @param systemInterface 类型:String
		 * @return 统计好的作业数
		 */
		//作业数统计
		private List<Tuple> systemInterfaceStatistics(String field,String fieldSystem,String systemInterface) {
			CriteriaBuilder cb = entityManager.getCriteriaBuilder();
			CriteriaQuery<Tuple> cq = cb.createTupleQuery();

			// 构建FROM
			Root<Field> rootField = cq.from(Field.class);
			Join<Field, FieldSystem> rootSystem = rootField.join("fieldSystems", JoinType.LEFT);
			Join<FieldSystem, SystemInterface> rootSystemInterface = rootSystem.join("systemInterfaces", JoinType.LEFT);
			
			// 构建GROUP BY部分
			cq.groupBy(rootField.get("name"));
			
			// 构建WHERE部分
			List<Predicate> predicatesList = new ArrayList<>();
			Collection<String> fieldSystemIds = userSessionService.findFieldSystemIdsOfCurrentAuthenticatedUserCanManage();
			predicatesList.add(rootSystem.get("id").in(fieldSystemIds));
			cq.where(predicatesList.toArray(new Predicate[predicatesList.size()]));

			// 构建SELECT部分
			cq.multiselect(rootField.get("name").alias("name"),rootField.get("id").alias("id"),
					cb.count(rootSystemInterface).alias("systemInterfaceAmount"));
			// 执行查询
			TypedQuery<Tuple> q = entityManager.createQuery(cq);
			List<Tuple> queryResult = q.getResultList();
			return queryResult;
		}
		/**
		 * 系统数和接口数的统计整合
		 * @param field 类型:String
		 * @param fieldSystem 类型:String
		 * @param systemInterface 类型:String
		 * @return 系统数和接口数的统计整合
		 */
		// 统计查询功能
		@RequiresPermissions(value={"governorControl:view"})
		@RequestMapping(value = "/statistics/forMonitorConsole", produces = "application/json")
		public String countByFieldAndSystem(String field, String fieldSystem,String systemInterface) {
			
			List<Tuple> queryResult1 = systemStatistics(field, fieldSystem,systemInterface);
			List<Tuple> queryResult2 = systemInterfaceStatistics(field, fieldSystem,systemInterface);

			HashMap<String, JsonObject> mixResult = new HashMap<>();
			
			for (Tuple tuple : queryResult1) {
				String id = tuple.get("id",String.class);
				String name = tuple.get("name", String.class);
				Long systemAmount = tuple.get("systemAmount", Long.class);
				
				JsonObject jo = mixResult.get(name);
				if(jo == null){
					jo = new JsonObject();
					jo.addProperty("name", name);
					jo.addProperty("id", id);
				}
				jo.addProperty("systemAmount", systemAmount);
				mixResult.put(name, jo);
			}
			for (Tuple tuple : queryResult2) {
				String id = tuple.get("id",String.class);
				String name = tuple.get("name", String.class);
				Long systemInterfaceAmount = tuple.get("systemInterfaceAmount", Long.class);

				
				JsonObject jo = mixResult.get(name);
				if(jo == null){
					jo = new JsonObject();
					jo.addProperty("name", name);
					jo.addProperty("id", id);
				}
				jo.addProperty("systemInterfaceAmount", systemInterfaceAmount);
				mixResult.put(name,jo);
			}
			
			JsonArray jsonDatas = new JsonArray();
			for(JsonObject jo : mixResult.values()){
				jsonDatas.add(jo);
			}
			
			JsonObject jsonResult = new JsonObject();
			jsonResult.add("content", jsonDatas);
			return jsonResult.toString();
		}
		

	@RequestMapping(value = "/updateInterface", produces = "application/json", method = RequestMethod.POST)
	@Transactional
	public String updateInterface(@RequestBody SystemInterfaceParam systemInterfaceParam) {

		JsonObject result = new JsonObject();
		SystemInterface systemInterface = systemInterfaceRepository
				.findOne(SystemInterface.idSpecification(systemInterfaceParam.getId()));
		
		if(!StringUtils.equals(systemInterface.getJobName(), systemInterfaceParam.getJobName())){
			if(systemInterfaceRepository.countByJobName(systemInterfaceParam.getJobName()) > 0){
				result.addProperty("backValue", "1");
				return result.toString();
			}
		}
		if(!StringUtils.equals(systemInterface.getJobCode(), systemInterfaceParam.getJobCode())){
			if(systemInterfaceRepository.countByJobCode(systemInterfaceParam.getJobCode()) > 0){
				result.addProperty("backValue", "2");
				return result.toString();
			}
		}
		// 更新接口前保存历史版本
		interfaceVersionHistoryService.save(InterfaceOperation.修改, null, false, systemInterface);

		systemInterface.setJobName(systemInterfaceParam.getJobName());
		// 联动更新R_JOB的信息
		systemInterface.getKettleJob().setName(systemInterfaceParam.getJobName());

		FieldSystem senderFieldSystem = fieldSystemRepository
				.findOne(FieldSystem.idSpecification(systemInterfaceParam.getSenderFieldSystemId()));
		FieldSystem receiverFieldSystem = fieldSystemRepository
				.findOne(FieldSystem.idSpecification(systemInterfaceParam.getReceiverFieldSystemId()));
		String checkJobCode = "ETL_"+senderFieldSystem.getCode()+"2"+receiverFieldSystem.getCode();
		if(!StringUtils.startsWith(systemInterfaceParam.getJobCode(),checkJobCode)){
			result.addProperty("backValue", "3");
			return result.toString();
		}
		systemInterface.setSenderFieldSystem(senderFieldSystem);
		systemInterface.setReceiverFieldSystem(receiverFieldSystem);
		systemInterface.setSenderDBType(systemInterfaceParam.getSenderDBType());
		systemInterface.setReceiverDBType(systemInterfaceParam.getReceiverDBType());
		systemInterface.setInterfaceScene(systemInterfaceParam.getInterfaceScene());
		systemInterface.setInterfaceDesc(systemInterfaceParam.getInterfaceDesc());
		systemInterface.setTecStandard(systemInterfaceParam.getTecStandard());
		systemInterface.setJobCode(systemInterfaceParam.getJobCode());
		//2016年6月20日08:49:56 增加数据源
		systemInterface.setSendKettleDataSource(systemInterfaceParam.getSendKettleDataSource());
		systemInterface.setReceiverKettleDataSource(systemInterfaceParam.getReceiverKettleDataSource());

		systemInterfaceRepository.save(Arrays.asList(systemInterface));

		// 记录用户日志
		String userLogContent = String.format("修改接口“%s”", systemInterface.getJobName());
		userLogService.save(UserLogOpt.MaintenanceInterface, null, userLogContent);

		
		result.addProperty("backValue", '0');
		return result.toString();
	}
		
		
}
